package server.conn;

import java.io.IOException;
import java.net.ServerSocket;

import server.Logger;

public abstract class ConnectionController extends Thread {
	protected int port;
	protected String name;
	protected ServerSocket serverSocket;
	protected volatile boolean listening;
	protected ThreadGroup connections;
	
	/**
	 * Constructor for an abstract ConnectionController
	 * @param port	Port to listen for connection on
	 * @param name	Name of the ConnectionController
	 */
	public ConnectionController(int port, String name) {
		this.port = port;
		this.name = name;
		this.serverSocket = null;
		this.listening = false;
		this.connections = new ThreadGroup(name+"connections");
	}
	
	/**
	 * Open up a connection on the serverSocket
	 */
	protected void startConnection() {
		try {
            serverSocket = new ServerSocket(port);
            serverSocket.setSoTimeout(1000);
            listening = true;
            Logger.getInstance().addLog(name+" has started on port "+port,1);
        } catch (IOException e) {
        	Logger.getInstance().addError("Could not start "+name+" on port: "+port,1);
            System.exit(-1);
        }
	}
	
	/**
	 * Closes the socket connection
	 */
	private void closeConnection() {
		try {
			serverSocket.close();
		} catch (IOException e) {
			Logger.getInstance().addError("Server socket could not be closed in "+name, 1);
		}
	}
	
	/**
	 * Must be over-ridden
	 */
	protected abstract void listen();
	
	/**
	 * Called when thread starts.  Starts the connection and begins listening.
	 */
	public void run() {
        startConnection();
        
        listen();

        closeConnection();
	}
	
	/**
	 * Stops the listening loop and shuts down all connection threads
	 */
	public void shutdown() {
		if (!listening) {
			System.out.println("Shutdown already called.");
		} else {
			System.out.println("Shutdown has been called.");
			listening = false;
		}
		
		Thread[] threadArray = new Thread[connections.activeCount()];
		connections.enumerate(threadArray);
		for (int x=0;x<threadArray.length;x++) {
			((ConnectionThread) threadArray[x]).kill();
		}
	}
	
	/**
	 * Check to see if a user is logged into another thread
	 * @param userName	Username to check for
	 * @return	True if the given userName is already logged in
	 */
	public boolean checkForUserName(String userName) {
		Thread[] threadArray = new Thread[connections.activeCount()];
		connections.enumerate(threadArray);
		for (int x=0;x<threadArray.length;x++) {
			if (((ConnectionThread) threadArray[x]).getUserName().compareToIgnoreCase(userName) == 0) {
				return true;
			}
		}
		
		return false;
	}
}
